package io.jsen.meta.diff.diff

import com.google.common.reflect.TypeToken
import io.jsen.meta.diff.obj.MetaObject
import io.jsen.meta.diff.support.MetaChangeModifier
import io.jsen.meta.diff.watch.MetaPath
import io.jsen.meta.diff.watch.MetaPathSearch
import spock.lang.Specification
import uk.co.jemos.podam.api.PodamFactory
import uk.co.jemos.podam.api.PodamFactoryImpl

import static io.jsen.meta.diff.context.DefaultMetaContext.instance
/**
 *
 * @author jsen*
 * @date 2021/09/18
 * */
class MetaDiffTest extends Specification {
    PodamFactory factory = new PodamFactoryImpl()

    def "基础类型测试"() {
        given:
        AllTypeContainer oldPojo = factory.manufacturePojo(AllTypeContainer.class)
        AllTypeContainer newPojo = factory.manufacturePojo(AllTypeContainer.class)
        when:
        MetaObject diffLong = instance.diffMeta(TypeToken.of(Long),
                newPojo.getId(), oldPojo.getId())
        MetaObject diffString = instance.diffMeta(TypeToken.of(String),
                newPojo.getName(), oldPojo.getName())
        MetaObject diffInteger = instance.diffMeta(TypeToken.of(Integer),
                newPojo.getAge(), oldPojo.getAge())
        MetaObject diffByte = instance.diffMeta(TypeToken.of(Byte),
                newPojo.getSex(), oldPojo.getSex())
        MetaObject diffBoolean = instance.diffMeta(TypeToken.of(Boolean),
                newPojo.getFunny(), oldPojo.getFunny())
        MetaObject diffCharacter = instance.diffMeta(TypeToken.of(Character),
                newPojo.getDesc(), oldPojo.getDesc())
        MetaObject diffDouble = instance.diffMeta(TypeToken.of(Double),
                newPojo.getWeight(), oldPojo.getWeight())
        MetaObject diffFloat = instance.diffMeta(TypeToken.of(Float),
                newPojo.getHigh(), oldPojo.getHigh())
        MetaObject diffShort = instance.diffMeta(TypeToken.of(Short),
                newPojo.getSpeed(), oldPojo.getSpeed())
        then:
        compareField(oldPojo.id, newPojo.id, diffLong)
        compareField(oldPojo.name, newPojo.name, diffString)
        compareField(oldPojo.age, newPojo.age, diffInteger)
        compareField(oldPojo.sex, newPojo.sex, diffByte)
        compareField(oldPojo.funny, newPojo.funny, diffBoolean)
        compareField(oldPojo.desc, newPojo.desc, diffCharacter)
        compareField(oldPojo.weight, newPojo.weight, diffDouble)
        compareField(oldPojo.high, newPojo.high, diffFloat)
        compareField(oldPojo.speed, newPojo.speed, diffShort)
    }


    def "complex测试"() {
        given:
        AllTypeContainer oldPojo = factory.manufacturePojo(AllTypeContainer.class)
        AllTypeContainer newPojo = factory.manufacturePojo(AllTypeContainer.class)
        oldPojo.setIndex("1")
        newPojo.setIndex("1")
        when:
        MetaObject obj = instance.diffMeta(TypeToken.of(AllTypeContainer), newPojo, oldPojo)
        then:
        compareComplexField(oldPojo.id, newPojo.id, obj, "id")
        compareComplexField(oldPojo.name, newPojo.name, obj, "name")
        compareComplexField(oldPojo.age, newPojo.age, obj, "age")
        compareComplexField(oldPojo.sex, newPojo.sex, obj, "sex")
        compareComplexField(oldPojo.funny, newPojo.funny, obj, "funny")
        compareComplexField(oldPojo.desc, newPojo.desc, obj, "desc")
        compareComplexField(oldPojo.weight, newPojo.weight, obj, "weight")
        compareComplexField(oldPojo.high, newPojo.high, obj, "high")
        compareComplexField(oldPojo.speed, newPojo.speed, obj, "speed")
        compareComplex(oldPojo, newPojo, obj)
    }


    def "ext测试"() {
        given:
        AllTypeContainer oldPojo = factory.manufacturePojo(AllTypeContainer.class)
        AllTypeContainer newPojo = factory.manufacturePojo(AllTypeContainer.class)
        oldPojo.setIndex("1")
        newPojo.setIndex("1")
        when:
        MetaObject obj = instance.diffMeta(TypeToken.of(AllTypeContainer), newPojo, oldPojo)
        then:
        compareComplexField(oldPojo.amount, newPojo.amount, obj, "amount")
        compareComplexField(oldPojo.amount2, newPojo.amount2, obj, "amount2")
        compareComplexField(oldPojo.timestamp, newPojo.timestamp, obj, "timestamp")
        compareComplexField(oldPojo.like, newPojo.like, obj, "like")
        compareComplexField(oldPojo.birthday, newPojo.birthday, obj, "birthday")
        compareComplexField(oldPojo.birth, newPojo.birth, obj, "birth")
        compareComplexField(oldPojo.current, newPojo.current, obj, "current")
        compareComplex(oldPojo, newPojo, obj)
    }

    def "容器测试"() {
    }

    static compareComplexField(oldVal, newVal, MetaObject obj, path) {
        return (oldVal == newVal) == MetaChangeModifier.isNoChange(
                MetaPathSearch.search(obj, MetaPath.builder(true).p(path).build())
                        .getModifier())
    }

    static compareComplex(AllTypeContainer oldVal, AllTypeContainer newVal, MetaObject obj) {
        return (
                oldVal.id == newVal.id &&
                        oldVal.name == newVal.name &&
                        oldVal.age == newVal.age &&
                        oldVal.sex == newVal.sex &&
                        oldVal.funny == newVal.funny &&
                        oldVal.desc == newVal.desc &&
                        oldVal.weight == newVal.weight &&
                        oldVal.high == newVal.high &&
                        oldVal.speed == newVal.speed
        ) == MetaChangeModifier.isNoChange(obj.getModifier())
    }

    static compareField(oldVal, newVal, MetaObject obj) {
        return (oldVal == newVal) == MetaChangeModifier.isNoChange(obj.getModifier())
    }

}